package com.fpswork.datamodel.basedao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.lang.reflect.Field;

import javax.persistence.Id;
import javax.servlet.http.HttpServletRequest;

import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import com.fps.web.model.BaseUser;
import com.fpswork.Helper.DBProductUtil;
import com.fpswork.common.Constant;
import com.fpswork.core.exception.exception.BusinessException;
import com.fpswork.core.exception.exception.SystemException;
import com.fpswork.core.model.ExcelEntity;
import com.fpswork.core.model.ExcelShell;
import com.fpswork.core.model.PageEntity;
import com.fpswork.datamodel.IPO;
import com.fpswork.datamodel.base.BaseSysDO;
import com.fpswork.util.JSONUtils;

public class BaseDao{
    @Autowired   
    HttpServletRequest request; //这里可以获取到request  
	@Autowired
    public JdbcTemplate jdbcTemplate;
	@Autowired
    protected SessionFactory sessionFactory;

    protected Session getCurrentSession(){
        return sessionFactory.getCurrentSession();
    }

    /**
     * 同Hibernate的SaveOrUpdate操作
     * @param table 类型：Object, Hibernate的Entity对象。
     * @return
     * @throws BusinessException
     **/
    public void saveOrUpdate(Object table) throws BusinessException {
        Session session= getCurrentSession();
        if(table instanceof IPO){
            if(session.contains(table)) {
                ((IPO) table).validatePO(((IPO) table).TYPE_UPDATE);
            }else{
                ((IPO) table).validatePO(((IPO) table).TYPE_INSERT);
            }
        }
        session.saveOrUpdate(table);
    }

    /**
     * 同Hibernate的SaveOrUpdate操作，批量SaveOrUpdate。
     * @param tableList 类型：List<Object> , Hibernate的Entity对象集合。
     * @return int 修改记录数量
     * @throws BusinessException
     **/
    public int saveOrUpdate(List tableList) throws BusinessException{
        int i=0;
        for(Object table:tableList){
            saveOrUpdate(table);
            i++;
        }
        return i;
    }

    /**
     * 将多条SQL查询结果取到<T> List<T>集合中。此处返回结果是Hibernate的处于持久态的Entity对象,而非普通JavaBean，开发者必须注意。
     * @param sql 类型：String, SQL语句。
     * @param c 类型：,Class<T>, 返回List泛型。
     * @return <T> List<T>，返回Hibernate的处于持久态的Entity对象集合。
     * @throws BusinessException
     */
    public  <T> List<T>  findBySql(String sql,Class<T> c) throws BusinessException{
        Session session= getCurrentSession();
        SQLQuery query = session.createSQLQuery(sql).addEntity("", c);
        return query.list();
    }

    
    
    
    
    /**
     * 将唯一的SQL查询结果取到<T>T对象中。此处返回结果是Hibernate的处于持久态的Entity对象,而非普通JavaBean，开发者必须注意。当sql语句返回多条记录时取第一条记录。
     * @param sql 类型：String, SQL语句。
     * @param c 类型：,Class<T>, 返回对象泛型。
     * @return <T>T，返回Hibernate的处于持久态的Entity对象。
     * @throws BusinessException
     */
    public  <T>T  findObjBySql(String sql,Class<T> c) throws BusinessException{
        if(sql==null||"".equals(sql)){
            throw new BusinessException("查询错误，查询语句("+sql+")不能为空！");
        }
        Session session= getCurrentSession();
        SQLQuery query = session.createSQLQuery(sql).addEntity("", c);
        return (T) query.uniqueResult();
    }

   
  

    /**
     * 将多条的查询结果取到List<Map>中
     * @param sql 类型：String, SQL语句。
     * @return List<Map>，返回结果集合List<Map>。
     * @throws BusinessException
     */
    public  List<Map> findBySql(String sql) throws BusinessException{
        Session session= getCurrentSession();
        SQLQuery query = session.createSQLQuery(sql);
        query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
        return query.list();
    }

    /**
     * 将唯一的查询结果取到Map中
     * @param sql 类型：String, SQL语句。
     * @return Map，返回查询的唯一一个结果集Map。
     * @throws BusinessException
     **/
    public  Map findObjBySql(String sql) throws BusinessException{
        Session session= getCurrentSession();
        SQLQuery query = session.createSQLQuery(sql);
        query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
        return (Map) query.uniqueResult();
    }

    /**
     * 同Hibernate的Save操作
     * @param table 类型：Object, Hibernate的Entity对象。
     * @return
     * @throws BusinessException
     **/
    public  void save(Object table) throws BusinessException{
        Session session= getCurrentSession();
        if(table!=null) {
            Class<?> clazz = table.getClass();
            for(; clazz != Object.class && clazz != BaseSysDO.class ;clazz = clazz.getSuperclass()) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    //获取字段中包含Id的注解
                    Id meta = field.getAnnotation(Id.class);
                    if (meta != null) {
                        try {
                            field.setAccessible(true);      //setAccessible这行代码把对象上的name字段设置为public访问属性.
                            Object id = field.get(table);
                            if ("".equals(id)) {
                                field.set(table, null);
                            }
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        if(table instanceof BaseSysDO){
            BaseSysDO tagTable=(BaseSysDO) table;
            String userId="";
            String userName="";
        	BaseUser user = (BaseUser) request.getSession().getAttribute(Constant.SESSION_USER_KEY);
            if(user!=null){
                userId= user.getId();
                userName=user.getUsername();
            }
            //为了给外部接口开放，未登录用户就无需保存登录信息
            /*else{
                throw new BusinessException("CurrentLoginHelper错误：未取得登陆信息。");
            }*/
            
            tagTable.setCreateuserid(userId);
            tagTable.setCreateusername(userName);
            tagTable.setCreatetime(new Date());
        }
        if(table instanceof IPO){
            ((IPO) table).validatePO(((IPO) table).TYPE_INSERT);
        }
        session.save(table);
    }

    /**
     * 同Hibernate的Save操作，批量保存。
     * @param tableList 类型：List<Object> , Hibernate的Entity对象集合。
     * @return int 保存记录数量
     * @throws BusinessException
     **/
    public int save(List  tableList  ) throws BusinessException{
        int i=0;
        for(Object table:tableList){
            save(table);
            i++;
        }
        return i;
    }

    /**
     * 同Hibernate的Update操作
     * @param table 类型：Object, Hibernate的Entity对象。
     * @return
     * @throws BusinessException
     **/
    public  void update(Object table) throws BusinessException{
        Session session=getCurrentSession();
        if(table instanceof BaseSysDO){
            BaseSysDO tagTable=(BaseSysDO) table;
            String userId="";
            String userName="";
            BaseUser user = (BaseUser) request.getSession().getAttribute(Constant.SESSION_USER_KEY);
            if(user!=null){
                userId= user.getId();
                userName=user.getUsername();
            }
            //为了给外部接口开放，未登录用户就无需保存登录信息
            /*else{
                throw new BusinessException("CurrentLoginHelper错误：未取得登陆信息。");
            }*/
            tagTable.setUpdateuserid(userId);
            tagTable.setUpdateusername(userName);
            tagTable.setUpdatetime(new Date());
        }
        if(table instanceof IPO){
            ((IPO) table).validatePO(((IPO) table).TYPE_UPDATE);
        }
        session.update(table);
    }

    /**
     * 同Hibernate的Update操作，批量Update。
     * @param tableList 类型：List<? extends Serializable> , Hibernate的Entity对象集合。
     * @return int 修改记录数量
     * @throws BusinessException
     **/
    public  int update(List tableList ) throws BusinessException{
        int i=0;
        for(Object table:tableList){
            update(table);
            i++;
        }
        return i;
    }

    /**
     * 同Hibernate的Delete操作
     * @param table 类型：Object, Hibernate的Entity对象。
     * @return
     * @throws BusinessException
     **/
    public  void delete(Object table) throws BusinessException{
        Session session=  getCurrentSession();
        if(table instanceof IPO){
            ((IPO) table).validatePO(((IPO) table).TYPE_DELETE);
        }
        session.delete(table);
    }

    /**
     * 同Hibernate的Delete操作，批量Delete。
     * @param tableList 类型：List<Object> , Hibernate的Entity对象集合。
     * @return int 删除记录数量
     * @throws BusinessException
     **/
    public  int delete(List tableList) throws BusinessException{
        Session session=  getCurrentSession();
        int i=0;
        for(Object table:tableList){
            if(table instanceof IPO){
                ((IPO) table).validatePO(((IPO) table).TYPE_DELETE);
            }
            session.delete(table);
            i++;
        }
        return i;
    }

    /**
     * 同Hibernate的Get操作。
     * @param table 类型：Class ,返回数据类型。
     * @param key 类型：Serializable 主键。
     * @return   Hibernate的Entity对象
     * @throws BusinessException
     **/
    public   <T> T get(Class<T> table,Serializable key) throws BusinessException{
        Session session= getCurrentSession();
        return (T) session.get(table, key);
    }

    /**
     * 同Hibernate的Get操作。
     * @param table 类型：Class ,返回数据类型。
     * @param key 类型：Serializable 主键。
     * @return   Hibernate的Entity对象
     * @throws BusinessException
     **/
    public <T> T load( Class<T> table, Serializable key) throws BusinessException{
        Session session= getCurrentSession();
        return (T) session.load(table, key);
    }

    /**
     * 同Hibernate的Flush操作。
     * @return
     * @throws BusinessException
     **/
    public void flush( ) throws BusinessException{
        Session session= getCurrentSession();
        session.flush();
    }

    /**
     * 同Hibernate的Merge操作。
     * @return
     * @throws BusinessException
     **/
    public void merge(Object table) throws BusinessException{
        Session session= getCurrentSession();
        session.merge(table);
    }

    /**
     * 同Hibernate的Refresh操作。
     * @return
     * @throws BusinessException
     **/
    public void refresh(Object table) throws BusinessException{
        Session session= getCurrentSession();
        session.refresh(table);
    }
    
    
    /**
     * 用于直接查询生成excel数据
     * @return
     * @throws BusinessException
     **/
    public ExcelEntity queryForExcelEntity(ExcelEntity excelEntity) {
        Session session= getCurrentSession();
        SQLQuery query = session.createSQLQuery(excelEntity.getSql());
        query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
        //查询出来的数据
        List<Map> lists = query.list();
        List<ExcelShell> filedata = new ArrayList<ExcelShell>();
        ExcelShell excelShell = new ExcelShell();
        //加载shell的表头
        Map<String, Object> titlemap= excelEntity.getLinename();
        excelShell.setTitlemap(titlemap);
    	//当前shell的页名
        excelShell.setShellname(excelEntity.getFilename().substring(0,excelEntity.getFilename().indexOf(".")));
        //shell需要加载的数据
        excelShell.setData(lists);
        filedata.add(excelShell);
        excelEntity.setFiledata(filedata);
    	return excelEntity;
	}
    
    
    
    

    //分页查询
    public PageEntity queryForPageEntity(PageEntity pageEntity) {
		int pagecount = pageEntity.getLimit();
		// 总记录数
		pageEntity =queryForCount(pageEntity);
		pageEntity =queryForData(pageEntity);
		int count =  pageEntity.getCount();
		if (pagecount == 0) {
			pageEntity.setPagesize(count);
		} else if (count % pagecount != 0) {
			pageEntity.setPagesize(count / pagecount + 1);
		} else {
			pageEntity.setPagesize(count / pagecount);
		}
		return pageEntity;
	}
    
    
    public PageEntity queryForCount(PageEntity pageEntity) {
			String sql = pageEntity.getSql();
			Session session= getCurrentSession();
	        SQLQuery query = session.createSQLQuery(sql);
	        query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
			try {
					int count = 0;
					count = (Integer)query.list().size();
					pageEntity.setCount(count);
					return pageEntity;
			} catch (Exception ex) {
				ex.printStackTrace();
				throw new SystemException();
			}
	}
    
    public PageEntity queryForData(PageEntity pageEntity) {
		String sql = pageEntity.getSql();
		int curpage = pageEntity.getPage();
		int pagecount = pageEntity.getLimit();
		DBProductUtil.getInstance(jdbcTemplate);
		String dbProductName = DBProductUtil.getProductName();
		if (pagecount == 0 || curpage == 0) {
			return null;
		} else if (curpage == 1) {
			if("Oracle".equals(dbProductName) ){
				sql = "select * from ( " + sql + ") where rownum <= " + pagecount;
			}else if("MySQL".equals(dbProductName)){
				sql = sql +" limit 0," + pagecount;
			}
		} else if (curpage > 1) {
			if("Oracle".equals(dbProductName) ){
				sql = "select * from (select spt.*,rownum rn from ( " + sql
						+ ")spt  where rownum <= " + pagecount * curpage
						+ ") where rn > " + pagecount * (curpage - 1);
			}else if("MySQL".equals(dbProductName)){
				sql =  sql+ " limit " + (pagecount * (curpage-1) )+ "," + pagecount;
			}
		}
		Session session= getCurrentSession();
        SQLQuery query = session.createSQLQuery(sql);
        query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
		try {
				pageEntity.setDatalist(query.list());
				pageEntity.setData(JSONUtils.parseArray(query.list()));
				return pageEntity;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new SystemException();
		}
}
	
}
